package client;

/**
 * Some code/concepts taken from: 
 * http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/SWTandThread.htm
 */

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.SWT;
import org.eclipse.wb.swt.SWTResourceManager;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.graphics.*;

import dictionary.gameEntities.*;
import dictionary.gameEntities.Card.CardType;
import server.data.*;

import dictionary.data.*;
import dictionary.interfaceData.*;
import dictionary.interfaceData.NetworkDataWrapper.ActionType;

public class AppWindow {

	final Display display = Display.getDefault();
	final AppWindow thisApp = this;
	protected Shell shlClueless;
	private CardIndex cardIndex = new CardIndex();	
	private FormToolkit formToolkit = new FormToolkit(display);
	private Table eventsTable;
	private Table cardSuspects, cardWeapons, cardRooms;
	
	private Combo moveOptions;	
	private Combo suggestSuspectOptions;
	private Combo suggestWeaponOptions;
	private Combo suggestRoomOptions;
	private Combo disproveCardOptions;
	private Combo accuseSuspectOptions;
	private Combo accuseWeaponOptions;
	private Combo accuseRoomOptions;
	private List<Combo> combos;
	
	private Label lblPlayerNextMove;
	private Label lblPlayerTurn;
	private List<ClueCharacter> playerLocations;
	private Canvas mapCanvas;
	private Image peacockImage;
	private Image ScarletImage;
	private Image MustardImage;
	private Image PlumImage;
	private Image WhiteImage;
	private Image GreenImage;
	private Image imageClueMap;
	
	private Client client;
	private Player assignedPlayer;
	private static final boolean DEBUG = false;
	Player assignedPlayerData;
	NetworkDataWrapper data;
	GameState currentGameState;
	List<StatusLogEntry> statusLog;
	SuggestOrAccuseData suggestionData;

	/**
	 * @param assignedPlayerData 
	 * @wbp.nonvisual location=91,181
	 */
	String ipAddress;
	int port;
	

	final Thread clientThread = new Thread("clientThread") {
		public void run() {
			try {
				Thread.sleep(1000L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			out("Hello from thread: \t" + Thread.currentThread().getName());
			client = new Client(ipAddress, port, display, thisApp);
			out("Bye from thread: \t" + Thread.currentThread().getName());
		}
	};
	private Button btnMove_Stay;
	private List<Button> buttons;
	private Button btnSuggest;
	private Button btnDisprove;
	private Button btnAccuse;
	private Button btnMove_Move;
	private Button btnAcc_Pass;

	public static void main(String[] args) {
		System.out.println("In AppWindow");
		new AppWindow();
	}
	protected void out(String string) {
		if (DEBUG) System.out.println(string);
	}
	
	private void setupImages() {
		peacockImage = 
				new Image(display, new ImageData(getClass().getClassLoader().getResourceAsStream("PeacockDot.png")));
		
		ScarletImage = 
				new Image(display, new ImageData(getClass().getClassLoader().getResourceAsStream("ScarletDot.png")));
		
		MustardImage = 
				new Image(display, new ImageData(getClass().getClassLoader().getResourceAsStream("MustardDot.png")));
		
		PlumImage = 
				new Image(display, new ImageData(getClass().getClassLoader().getResourceAsStream("PlumDot.png")));
		
		WhiteImage = 
				new Image(display, new ImageData(getClass().getClassLoader().getResourceAsStream("WhiteDot.png")));
		
		GreenImage = 
				new Image(display, new ImageData(getClass().getClassLoader().getResourceAsStream("GreenDot.png")));
		 
	}
	
	/**
	 * Launch the application.
	 */
	public AppWindow() {
		this("localhost", 9999);
	}
	
	public AppWindow(String ipAddressIn, int portIn) {
		ipAddress = ipAddressIn;
		port = portIn;
		debug("opening.");
		clientThread.start();
		open();
		debug("opened.");
		debug("starting Client class.");
		debug("Client started.");
	}
	

    private void debug(String textIn) {
    	System.out.println("-----AppWindow:"+textIn);		
	}


	public class GUIUpdater implements Runnable
    {
		// use gameState
    	GUIUpdater(NetworkDataWrapper dataIn)
    	{
    		data = dataIn;
    	}
    	public void run() {
    		out("GUI DATA RECEIVED");
    		out(data.toString());
    		//    		lblPlayerNextMove.setText(data.gameState.nextActionText);
    		currentGameState = data.gameState;
    		// suggestionData: need to know what other user suggested 
    		suggestionData = data.suggestionOrAccusation;
    		
    		// look at type - switch statement
    		// accordingly pull GameState, and also Player data if appropriate
    		switch (data.currentAction) {
    		case GAME_STATE_CHANGE:
    			out("-------------statusLog-----------");
    			out(statusLog.toString());
    			statusLog = data.statusLogEntries.get(assignedPlayer);
    			out("received game state "+data.gameState.toString());
				updateGUIState(currentGameState, statusLog, suggestionData);
    			break;
    		case INIT_PLAYER:
    			out("Initializing Player");
    			assignedPlayerData = data.playerData;
    			out("received player data"+data.playerData.toString());
    			updateGUIWithPlayerData(assignedPlayerData);
    			out("-------------statusLog-----------");
    			out(assignedPlayer.toString());
    			statusLog = data.statusLogEntries.get(assignedPlayer);
				out(statusLog.toString());
				updateGUIState(currentGameState, statusLog, suggestionData);
    			break;
    		// we won't call user action
    		case USER_ACTION:
    			throw new RuntimeException("Invalid Server to Client message type");
    		}
    	}
		private void out(String string) {
			if (DEBUG) System.out.println(string);
		}
    };
    

	public void updateGUIWithPlayerData(Player assignedPlayerData)
	{
		this.assignedPlayer = assignedPlayerData;
		// change title bar to show player (character's) name
		shlClueless.setText("ClueLess - "+this.assignedPlayer.character.getName());
		showCards(assignedPlayer.playerCards);
		// take the character and update the GUI to show the user who he is.
	}
	
	public void updateGUIState(GameState currentGameState, 
			List<StatusLogEntry> statusLog, SuggestOrAccuseData suggestionData)
	{
		out("GUI updating Game State with\n"+currentGameState.toString());
		displayGameBoard(currentGameState.weaponPositions, currentGameState.charactersPositions);
		displayStatusMessages(statusLog);
		enableActionsAndUpdatePrompts(currentGameState.currentPlayer, 
				currentGameState.pendingAction, currentGameState.nextActionText,
				suggestionData, currentGameState.charactersPositions);
		// use GameState to refresh the GUI components 
	}
	
	public void showCards(Hand playerCards) {
		ArrayList<Card> roomCards = playerCards.getCards(Card.CardType.ROOM);
		ArrayList<Card> suspectCards = playerCards.getCards(Card.CardType.CHARACTER);
		ArrayList<Card> weaponCards = playerCards.getCards(Card.CardType.WEAPON);
		
		for (Card roomIndex: roomCards) {
			TableItem item = new TableItem (cardRooms, SWT.NONE);
			item.setText(roomIndex.getCardName());
		}
		
		for (Card suspectIndex: suspectCards) {
			TableItem item = new TableItem (cardSuspects, SWT.NONE);
			item.setText(suspectIndex.getCardName());
		}
		
		
		for (Card weaponIndex: weaponCards) {
			TableItem item = new TableItem (cardWeapons, SWT.NONE);
			item.setText(weaponIndex.getCardName());
		}
	}
	
	// determine if you are the active player
	// determine what action you should be taking
	// show the next Action text based on what is found here.
	// if the user is disproving, they should only be able to select 
	// cards from their hand that are within the suggestion data
	public void enableActionsAndUpdatePrompts(Player currentPlayer,
			UserActionTypes pendingAction, String nextActionText, 
			SuggestOrAccuseData suggestionData, ArrayList<ClueCharacter> charactersPositions) {
		if (currentPlayer.playerId==(this.assignedPlayer.playerId))
		{
			lblPlayerTurn.setText("Your turn.");
			out("Assigned Player: "+this.assignedPlayer.toString());
			lblPlayerNextMove.setText(nextActionText);
			
			// hack
			ClueCharacter foundCharacter = null;
			for (ClueCharacter curr: charactersPositions)
			{
				if (curr.getId() == assignedPlayer.character.getId())
				{
					foundCharacter = curr;
				}
			}
			if (foundCharacter.getLocation().getId()!=this.assignedPlayer.character.getLocation().getId())
			{
				Location l = LocationIndex.getLocationByName(foundCharacter.getLocation().getName());
				out("new location: "+l.toString());
				this.assignedPlayer.character.setLocation(l);
			}
			
			// it's our turn to do something
			switch (pendingAction)
			{
			case ACCUSE:
				accuseRoomOptions.setEnabled(true);
				accuseSuspectOptions.setEnabled(true);
				accuseWeaponOptions.setEnabled(true);
				btnAccuse.setEnabled(true);
				btnAcc_Pass.setEnabled(true);
				break;
			case DISPROVE:
				refreshDisproveOptions(suggestionData);
				disproveCardOptions.setEnabled(true);
				btnDisprove.setEnabled(true);
				break;
			case PLAYER_MOVE:
				
				refreshMoveOptions(charactersPositions);
				btnMove_Move.setEnabled(true);
				if (foundCharacter.isMovedBySuggestion())
				{
					btnMove_Stay.setEnabled(true);
				}
				else
				{
					btnMove_Stay.setEnabled(false);
				}
				this.moveOptions.setEnabled(true);
				break;
			case SUGGEST:
				btnSuggest.setEnabled(true);
				suggestRoomOptions.setText(assignedPlayer.character.getLocation().getName());
				suggestSuspectOptions.setEnabled(true);
				suggestWeaponOptions.setEnabled(true);
				
				break;
			}
		}
		else if (currentPlayer.playerId > 90)
		{
			lblPlayerTurn.setText("");
			lblPlayerNextMove.setText("");
			disablePlayerActions();
		}
		else
		{
			lblPlayerTurn.setText("Awaiting "+pendingAction.getReadableName()+
					" by "+currentPlayer.character.getName());
			lblPlayerNextMove.setText("Awaiting "+pendingAction.getReadableName()+
					" by "+currentPlayer.character.getName());
			disablePlayerActions();
		}
	}

	private void disablePlayerActions() 
	{
		for (Combo curr : combos)
		{
			curr.setEnabled(false);
		}
		
		for (Button curr : buttons)
		{
			curr.setEnabled(false);
		}
		
	}
	
	// show whose turn it is
	public void displayPlayerTurnMessage(String playerTurnStatus) {
		// TODO Auto-generated method stub
		
	}

	public void displayStatusMessages(List<StatusLogEntry> statusLog) {
		eventsTable.removeAll();
		for (StatusLogEntry entry: statusLog) {
 			TableItem item = new TableItem (eventsTable, SWT.NONE);
 			item.setText(entry.toString());
		}
	}

	public void displayGameBoard(List<Weapon> weaponPositions,
			List<ClueCharacter> charactersPositions) {
		// TODO Auto-generated method stub
		
		playerLocations = charactersPositions;
		mapCanvas.redraw();
		
	}
	
	public void UserActionListener()
	{
		// waits for user to take an action.  Then calls the appropriate ClientLogic method
	}

	/**
	 * Open the window.
	 */
	public void open() {
		createContents();
		debug("created contents");
		shlClueless.open();
		debug("opened shell");
		shlClueless.layout();
		debug("GUI Waiting for changes");
		while (!shlClueless.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		
		display.dispose();
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shlClueless = new Shell(display);
		shlClueless.setMinimumSize(new Point(850, 735));
		shlClueless.setSize(922, 735);
		shlClueless.setText("Clue-Less");
		
		Device device = Display.getCurrent ();
		Color backgroundColor = new Color (device, 240, 240, 240);
		formToolkit.setBackground(backgroundColor);
		InputStream input = getClass().getClassLoader().getResourceAsStream("ClueLessMap_HallwayLabels.jpg");
		ImageData imageData = new ImageData(input);
		
		imageClueMap = new Image( shlClueless.getDisplay(), imageData);
		 final int width = imageClueMap.getBounds().width;
		 final int height = imageClueMap.getBounds().height;
		shlClueless.setLayout(null);
		
		setupImages();
		
		mapCanvas = new Canvas(shlClueless,SWT.NO_REDRAW_RESIZE);
		mapCanvas.setForeground(SWTResourceManager.getColor(SWT.COLOR_RED));
		mapCanvas.setBounds(20, 28, 497, 403);
		mapCanvas.addPaintListener(new PaintListener() {
	        public void paintControl(PaintEvent e) {
	            e.gc.drawImage(imageClueMap,0,0,width,height, 0,0, mapCanvas.getSize().x, mapCanvas.getSize().y);
	        	
	            if (playerLocations != null) {
	            	for  (ClueCharacter character: playerLocations) {
	            		
	            		Image characterImage = null;
	            		MapXY characterXY = null;
	            		MapXY locationXY = null;
	            		boolean isHall = false;
	            		
	            		switch (character.getName()) {
	            		case "Miss Scarlet": characterImage = ScarletImage; characterXY = MapXY.SCARLET; break;
	            		case "Col. Mustard": characterImage = MustardImage; characterXY = MapXY.MUSTARD; break;
	            		case "Prof. Plum": characterImage = PlumImage; characterXY = MapXY.PLUM; break;
	            		case "Mr. Green": characterImage = GreenImage; characterXY = MapXY.GREEN; break;
	            		case "Mrs. White": characterImage = WhiteImage; characterXY = MapXY.WHITE; break;
	            		case "Mrs. Peacock": characterImage = peacockImage; characterXY = MapXY.PEACOCK; break;
	            		}
	            		
	            		switch (character.getLocation().getName()) {
	            		case "Study": locationXY = MapXY.STUDY; break;
	            		case "Hall": locationXY = MapXY.HALL; break;
	            		case "Lounge": locationXY = MapXY.LOUNGE; break;
	            		case "Library": locationXY = MapXY.LIBRARY; break;
	            		case "Billiard Room": locationXY = MapXY.BILLARD_ROOM; break;
	            		case "Dining Room": locationXY = MapXY.DINNER_ROOM; break;
	            		case "Conservatory": locationXY = MapXY.CONSERVATORY; break;
	            		case "Ball Room": locationXY = MapXY.BALLROOM; break;
	            		case "Kitchen": locationXY = MapXY.KITCHEN; break;
	            		case "Hall 1": locationXY = MapXY.HALL1; isHall = true; break;
	            		case "Hall 2": locationXY = MapXY.HALL2; isHall = true; break;
	            		case "Hall 3": locationXY = MapXY.HALL3; isHall = true; break;
	            		case "Hall 4": locationXY = MapXY.HALL4; isHall = true; break;
	            		case "Hall 5": locationXY = MapXY.HALL5; isHall = true; break;
	            		case "Hall 6": locationXY = MapXY.HALL6; isHall = true; break;
	            		case "Hall 7": locationXY = MapXY.HALL7; isHall = true; break;
	            		case "Hall 8": locationXY = MapXY.HALL8; isHall = true; break;
	            		case "Hall 9": locationXY = MapXY.HALL9; isHall = true; break;
	            		case "Hall 10": locationXY = MapXY.HALL10; isHall = true; break;
	            		case "Hall 11": locationXY = MapXY.HALL11; isHall = true; break;
	            		case "Hall 12": locationXY = MapXY.HALL12; isHall = true; break;
	            		}
	            		
	            		if(!isHall) {
	            		e.gc.drawImage(characterImage,locationXY.x() + characterXY.x(),locationXY.y() + characterXY.y());
	            		}
	            		else {
	            		e.gc.drawImage(characterImage,locationXY.x(),locationXY.y());		
	            		}
	            	}
	            	}
	        	}
	    });
				
		lblPlayerTurn = new Label(shlClueless, SWT.NONE);
		lblPlayerTurn.setBounds(10, 10, 384, 18);
		lblPlayerTurn.setBackground(backgroundColor);
		lblPlayerTurn.setFont(SWTResourceManager.getFont("Lucida Grande", 10, SWT.BOLD));
		formToolkit.adapt(lblPlayerTurn, true, true);
		lblPlayerTurn.setText("Awaiting move from Colonel Mustard ");
		lblPlayerTurn.setBackground(backgroundColor);
		
		eventsTable = new Table(shlClueless, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION );
		eventsTable.setBounds(530, 28, 237, 403);
		eventsTable.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		//formToolkit.adapt(eventsTable);
		formToolkit.paintBordersFor(eventsTable);
		eventsTable.setLinesVisible(true);
		
		TableColumn tblclmnEvent = new TableColumn(eventsTable, SWT.NONE);
		tblclmnEvent.setWidth(237);
		tblclmnEvent.setText("Event");
		
		
//		ArrayList<String> Status = new ArrayList<String>();
//		for (int statusIdx =0; statusIdx<10000; statusIdx++) {
//			Status.add( statusIdx +"Mrs. White moves \ninto the Observatory");
//			Status.add("Mrs. White suggests: Col. Mustard in \nthe Observatory, with the Candlestick ");
//		}
		//Status.add(new String[] {"Mrs. Peacock cannot disprove the suggestion"});
		//Status.add(new String[] {"Col. Mustard disproves the suggestion!"});
		//Status.add(new String[] {"Mrs. White moves into", "the Observatory"});
		//Status.add(new String[] {"Mrs. White suggests: Col. Mustard," , "nin the Observatory, with the Candlestick"});
		//Status.add(new String[] {"Mrs. Peacock cannot disprove the suggestion"});
		//Status.add(new String[] {"Col. Mustard disproves the suggestion!"});
		
		
		final int TEXT_MARGIN = 10;
		eventsTable.addListener(SWT.MeasureItem, new Listener() {
				   public void handleEvent(Event event) {
				      TableItem item = (TableItem)event.item;
				      String text = item.getText(event.index);
				      Point size = event.gc.textExtent(text);
				      event.width = size.x + 2 * TEXT_MARGIN;
				      event.height = Math.max(event.height, size.y + TEXT_MARGIN);
				   }
				});
		
		Label label = new Label(shlClueless, SWT.SEPARATOR | SWT.VERTICAL);
		label.setBounds(190, 484, 11, 211);
		formToolkit.adapt(label, true, true);
		
		Label label_1 = new Label(shlClueless, SWT.SEPARATOR | SWT.VERTICAL);
		label_1.setBounds(414, 484, 6, 211);
		formToolkit.adapt(label_1, true, true);
		
		Label label_2 = new Label(shlClueless, SWT.SEPARATOR | SWT.VERTICAL);
		label_2.setBounds(640, 640, 0, 159);
		formToolkit.adapt(label_2, true, true);
		
		Label lblMove = new Label(shlClueless, SWT.SHADOW_NONE);
		lblMove.setBounds(20, 489, 59, 18);
		lblMove.setImage(null);
		lblMove.setFont(SWTResourceManager.getFont("Lucida Grande", 10, SWT.BOLD));
		formToolkit.adapt(lblMove, true, true);
		lblMove.setText("Move");
		
		Label lblSuggest = new Label(shlClueless, SWT.NONE);
		lblSuggest.setBounds(222, 487, 80, 18);
		lblSuggest.setImage(null);
		lblSuggest.setFont(SWTResourceManager.getFont("Lucida Grande", 10, SWT.BOLD));
		lblSuggest.setText("Suggest");
		formToolkit.adapt(lblSuggest, true, true);
		
		Label lblDisprove = new Label(shlClueless, SWT.NONE);
		lblDisprove.setBounds(448, 489, 69, 18);
		lblDisprove.setFont(SWTResourceManager.getFont("Lucida Grande", 10, SWT.BOLD));
		lblDisprove.setText("Disprove");
		formToolkit.adapt(lblDisprove, true, true);
		
		Label label_5 = new Label(shlClueless, SWT.SEPARATOR);
		label_5.setBounds(632, 496, 2, 181);
		formToolkit.adapt(label_5, true, true);
		
		Label lblNewLabel_1 = new Label(shlClueless, SWT.NONE);
		lblNewLabel_1.setBounds(646, 484, 59, 18);
		lblNewLabel_1.setFont(SWTResourceManager.getFont("Lucida Grande", 10, SWT.BOLD));
		formToolkit.adapt(lblNewLabel_1, true, true);
		lblNewLabel_1.setText("Accuse");
		
		lblPlayerNextMove = new Label(shlClueless, SWT.NONE);
		lblPlayerNextMove.setBounds(20, 450, 384, 18);
		lblPlayerNextMove.setText("");
		lblPlayerNextMove.setFont(SWTResourceManager.getFont("Lucida Grande", 11, SWT.BOLD));
		lblPlayerNextMove.setBackground(SWTResourceManager.getColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT));
		lblPlayerNextMove.setBackground(SWTResourceManager.getColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT));
		

		btnMove_Stay = new Button(shlClueless, SWT.NONE);
		btnMove_Stay.setBounds(104, 601, 80, 18);
		btnMove_Stay.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				stay();
				disablePlayerActions();
			}
		});
		btnMove_Stay.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(btnMove_Stay, true, true);
		btnMove_Stay.setText("Stay");
		
		buttons = new ArrayList<Button>();
		buttons.add(btnMove_Stay);
		
		btnSuggest = new Button(shlClueless, SWT.NONE);
		btnSuggest.setBounds(312, 655, 80, 18);
		btnSuggest.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		btnSuggest.addSelectionListener(new SelectionAdapter() {
		      public void widgetDefaultSelected(SelectionEvent e) {
		      }
		      public void widgetSelected(SelectionEvent e) {
		    	  trySuggestion((Room)LocationIndex.getLocationByName(suggestRoomOptions.getText()), 
		    			  CharacterIndex.getCharacterByName(suggestSuspectOptions.getText()), 
		    			  WeaponIndex.getWeaponByName(suggestWeaponOptions.getText()));
		    	  disablePlayerActions();
		      }
			
		});
		btnSuggest.setText("Suggest");
		formToolkit.adapt(btnSuggest, true, true);
		buttons.add(btnSuggest);
		
		btnDisprove = new Button(shlClueless, SWT.NONE);
		btnDisprove.setBounds(524, 584, 87, 18);
		btnDisprove.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		btnDisprove.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				tryDisproval(cardIndex.getCardByName(disproveCardOptions.getText()));
				disablePlayerActions();
			}
		});
		btnDisprove.setText("Disprove");
		formToolkit.adapt(btnDisprove, true, true);
		buttons.add(btnDisprove);
		
		btnAccuse = new Button(shlClueless, SWT.NONE);
		btnAccuse.setBounds(776, 658, 68, 18);
		btnAccuse.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		btnAccuse.setText("Accuse");
		btnAccuse.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				tryAccusation((Room)LocationIndex.getLocationByName(accuseRoomOptions.getText()), 
		    			  CharacterIndex.getCharacterByName(accuseSuspectOptions.getText()), 
		    			  WeaponIndex.getWeaponByName(accuseWeaponOptions.getText()));
				disablePlayerActions();
			}
		});
		formToolkit.adapt(btnAccuse, true, true);
		buttons.add(btnAccuse);
		
		
		moveOptions = new Combo(shlClueless, SWT.NONE);
		moveOptions.setBounds(21, 541, 163, 23);
		formToolkit.adapt(moveOptions);
		formToolkit.paintBordersFor(moveOptions);
		
		combos = new ArrayList<Combo>();
		combos.add(moveOptions);

		suggestSuspectOptions = new Combo(shlClueless, SWT.NONE);
		for (ClueCharacter curr : CharacterIndex.getCharacters())
		{
			suggestSuspectOptions.add(curr.getName());
		}
		suggestSuspectOptions.select(0);
		suggestSuspectOptions.setBounds(231, 539, 163, 23);
		formToolkit.adapt(suggestSuspectOptions);
		formToolkit.paintBordersFor(suggestSuspectOptions);
		combos.add(suggestSuspectOptions);
		
		suggestWeaponOptions = new Combo(shlClueless, SWT.NONE);
		for (Weapon currWeapon : WeaponIndex.getWeapons())
		{
			suggestWeaponOptions.add(currWeapon.getName());
		}
		suggestWeaponOptions.select(0);
		suggestWeaponOptions.setBounds(230, 582, 163, 23);
		formToolkit.adapt(suggestWeaponOptions);
		formToolkit.paintBordersFor(suggestWeaponOptions);
		combos.add(suggestWeaponOptions); 
		
		suggestRoomOptions = new Combo(shlClueless, SWT.NONE);
		for (Location currRoom : LocationIndex.getAllRooms())
		{
			suggestRoomOptions.add(currRoom.getName());
		}
		suggestRoomOptions.select(0);
		suggestRoomOptions.setBounds(231, 626, 163, 23);
		formToolkit.adapt(suggestRoomOptions);
		formToolkit.paintBordersFor(suggestRoomOptions);
		combos.add(suggestRoomOptions);
		
		disproveCardOptions = new Combo(shlClueless, SWT.NONE);
		disproveCardOptions.setBounds(448, 541, 163, 23);
		formToolkit.adapt(disproveCardOptions);
		formToolkit.paintBordersFor(disproveCardOptions);
		combos.add(disproveCardOptions);
		
		accuseSuspectOptions = new Combo(shlClueless, SWT.NONE);
		for (ClueCharacter curr : CharacterIndex.getCharacters())
		{
			accuseSuspectOptions.add(curr.getName());
		}
		accuseSuspectOptions.select(0);
		accuseSuspectOptions.setBounds(681, 536, 163, 23);
		formToolkit.adapt(accuseSuspectOptions);
		formToolkit.paintBordersFor(accuseSuspectOptions);
		combos.add(accuseSuspectOptions);
		
		accuseWeaponOptions = new Combo(shlClueless, SWT.NONE);
		for (Weapon currWeapon : WeaponIndex.getWeapons())
		{
			accuseWeaponOptions.add(currWeapon.getName());
		}
		accuseWeaponOptions.select(0);
		accuseWeaponOptions.setBounds(679, 586, 163, 23);
		formToolkit.adapt(accuseWeaponOptions);
		formToolkit.paintBordersFor(accuseWeaponOptions);
		combos.add(accuseWeaponOptions);
		
		accuseRoomOptions = new Combo(shlClueless, SWT.NONE);
		for (Location currRoom : LocationIndex.getAllRooms())
		{
			accuseRoomOptions.add(currRoom.getName());
		}
		accuseRoomOptions.select(0);
		accuseRoomOptions.setBounds(679, 630, 163, 23);
		formToolkit.adapt(accuseRoomOptions);
		formToolkit.paintBordersFor(accuseRoomOptions);
		combos.add(accuseRoomOptions);
		
		Label lblSelectCard = new Label(shlClueless, SWT.NONE);
		lblSelectCard.setBounds(448, 523, 94, 14);
		lblSelectCard.setBackgroundImage(null);
		lblSelectCard.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(lblSelectCard, true, true);
		lblSelectCard.setText("Select Card");
		
		Label lblSuspect = new Label(shlClueless, SWT.NONE);
		lblSuspect.setBounds(230, 523, 81, 14);
		lblSuspect.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		lblSuspect.setText("Suspect");
		formToolkit.adapt(lblSuspect, true, true);
		
		Label lblWeapon = new Label(shlClueless, SWT.NONE);
		lblWeapon.setBounds(679, 566, 81, 14);
		lblWeapon.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		lblWeapon.setText("Weapon");
		formToolkit.adapt(lblWeapon, true, true);
		
		Label lblRoom = new Label(shlClueless, SWT.NONE);
		lblRoom.setBounds(679, 610, 81, 14);
		lblRoom.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		lblRoom.setText("Room");
		formToolkit.adapt(lblRoom, true, true);
		
		Label lblSuspect_1 = new Label(shlClueless, SWT.NONE);
		lblSuspect_1.setBounds(681, 516, 59, 14);
		lblSuspect_1.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(lblSuspect_1, true, true);
		lblSuspect_1.setText("Suspect");
		
		Label lblWeapon_1 = new Label(shlClueless, SWT.NONE);
		lblWeapon_1.setBounds(237, 562, 59, 14);
		lblWeapon_1.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(lblWeapon_1, true, true);
		lblWeapon_1.setText("Weapon");
		
		Label lblRoom_1 = new Label(shlClueless, SWT.NONE);
		lblRoom_1.setBounds(237, 606, 59, 14);
		lblRoom_1.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(lblRoom_1, true, true);
		lblRoom_1.setText("Room");
		
		Label lblSelectRoom = new Label(shlClueless, SWT.NONE);
		lblSelectRoom.setBounds(20, 521, 94, 14);
		lblSelectRoom.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(lblSelectRoom, true, true);
		lblSelectRoom.setText("Select Room");
		
		btnMove_Move = new Button(shlClueless, SWT.NONE);
		btnMove_Move.setBounds(104, 580, 80, 18);
		btnMove_Move.setText("Move");
		btnMove_Move.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		btnMove_Move.addSelectionListener(new SelectionAdapter() {
			@Override
		      public void widgetSelected(SelectionEvent e) {
		    	  moveToLocation(LocationIndex.getLocationByName(moveOptions.getText()));
		    	  disablePlayerActions();
		      }
		});
		formToolkit.adapt(btnMove_Move, true, true);
		buttons.add(btnMove_Move);
		
		btnAcc_Pass = new Button(shlClueless, SWT.NONE);
		btnAcc_Pass.setBounds(776, 682, 69, 18);
		btnAcc_Pass.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				tryAccusation(null, null, null);
				disablePlayerActions();
			}
		});
		btnAcc_Pass.setText("Pass");
		btnAcc_Pass.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(btnAcc_Pass, true, true);
		buttons.add(btnAcc_Pass);
		
		Label lblEvents = new Label(shlClueless, SWT.SHADOW_NONE);
		lblEvents.setBounds(530, 10, 59, 18);
		lblEvents.setBackground(SWTResourceManager.getColor(240, 240, 240));
		lblEvents.setText("Events");
		lblEvents.setFont(SWTResourceManager.getFont("Lucida Grande", 10, SWT.BOLD));
		formToolkit.adapt(lblEvents, true, true);
		
		Group grpCards = new Group(shlClueless, SWT.NONE);
		grpCards.setFont(SWTResourceManager.getFont("Lucida Sans Unicode", 10, SWT.BOLD));
		grpCards.setText("Cards");
		grpCards.setBounds(781, 10, 125, 428);
		formToolkit.adapt(grpCards);
		formToolkit.paintBordersFor(grpCards);
		
		cardSuspects = new Table(grpCards, SWT.BORDER | SWT.FULL_SELECTION);
		cardSuspects.setHeaderVisible(true);
		cardSuspects.setBounds(13, 22, 102, 118);
		cardSuspects.setLinesVisible(true);
		cardSuspects.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(cardSuspects);
		formToolkit.paintBordersFor(cardSuspects);
		
		TableColumn tblclmnSuspects = new TableColumn(cardSuspects, SWT.NONE);
		tblclmnSuspects.setWidth(100);
		tblclmnSuspects.setText("Suspects");
		
		cardWeapons = new Table(grpCards, SWT.BORDER | SWT.FULL_SELECTION);
		cardWeapons.setBounds(13, 151, 102, 118);
		cardWeapons.setHeaderVisible(true);
		cardWeapons.setLinesVisible(true);
		cardWeapons.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(cardWeapons);
		formToolkit.paintBordersFor(cardWeapons);
		
		TableColumn tblclmnWeapons = new TableColumn(cardWeapons, SWT.NONE);
		tblclmnWeapons.setWidth(100);
		tblclmnWeapons.setText("Weapons");
		
		cardRooms = new Table(grpCards, SWT.BORDER | SWT.FULL_SELECTION);
		cardRooms.setHeaderVisible(true);
		cardRooms.setBounds(13, 285, 102, 118);
		cardRooms.setLinesVisible(true);
		cardRooms.setFont(SWTResourceManager.getFont("Lucida Grande", 8, SWT.BOLD));
		formToolkit.adapt(cardRooms);
		formToolkit.paintBordersFor(cardRooms);
		
		TableColumn tblclmnRooms = new TableColumn(cardRooms, SWT.NONE);
		tblclmnRooms.setWidth(100);
		tblclmnRooms.setText("Rooms");
	    
	    debug("created all stuff");
	    
	    disablePlayerActions();
	    this.lblPlayerTurn.setText("Waiting for game to begin.");
	}

	private void refreshDisproveOptions(SuggestOrAccuseData suggestionDataIn) {
		// do with disproval action
		disproveCardOptions.removeAll();
		for (Card card : this.assignedPlayer.playerCards.getCards(CardType.ANY))
		{
			if (card.getCardName().equals(suggestionDataIn.getRoom().getName()) ||
				card.getCardName().equals(suggestionDataIn.getSuspect().getName()) ||
				card.getCardName().equals(suggestionDataIn.getWeapon().getName()))
			{
				disproveCardOptions.add(card.getCardName());
			}
		}
		disproveCardOptions.select(0);
	}
/*
 * 	//method updated to not populate move options with hallways that another character is already in - DL
	private void refreshMoveOptions() {
		// update the moveOptions combo box
		boolean tempPlayerFound;
		ClueCharacter cc;
		//List<ClueCharacter> playerLocations;
		Iterator<ClueCharacter> playerLocationsIterator = playerLocations.iterator();
		moveOptions.removeAll();
		out("start refresh");
		for (Location l : getPlayerLocation().getAllConnections())
		{
			tempPlayerFound = false;
			while(playerLocationsIterator.hasNext())
			{
				cc = playerLocationsIterator.next();
				if (!cc.getLocation().isRoom())
				{
					if (cc.getLocation().getId() == l.getId())
					{
						tempPlayerFound = true;
					}
				}
			}
			if (!tempPlayerFound)
			{
				out("refreshing: "+l.getName());
				moveOptions.add(l.getName());
			}	
		}
		moveOptions.redraw();
		moveOptions.select(0);
	}
 */
	private void refreshMoveOptions(List<ClueCharacter> characterLocations) {
		// update the moveOptions combo box
		moveOptions.removeAll();
		out("start refresh");
		Location locWithLinks = LocationIndex.getLocationByName(this.assignedPlayer.character.getLocation().getName());
		this.assignedPlayer.character.setLocation(locWithLinks);
		out("new location: "+locWithLinks.toString());
		out(locWithLinks.toString());
		for (Location l : locWithLinks.getAllConnections())
		{
			out("refreshing: "+l.getName());
			if (l.isRoom()) {
				moveOptions.add(l.getName());
			}
			else {
				boolean hallOccupied = false;
				for (ClueCharacter c : characterLocations) {
					if (c.getLocation().getId()==(l.getId())) {hallOccupied = true;} 	
				}
				if(!hallOccupied) {moveOptions.add(l.getName());}
			}
		}
		moveOptions.redraw();
		moveOptions.select(0);
	}

	private Location getPlayerLocation() {
		return this.assignedPlayer.character.getLocation();
	}

	//////////////////////////////////////////////////////////////////////////
	//  User action responses
	//////////////////////////////////////////////////////////////////////////
	
	public void moveToLocation(Location location)
	{
		// creates Player move object with new location, puts into network wrapper 
		PlayerMoveData object = new PlayerMoveData();
		out(this.assignedPlayerData.toString());
		object.setMovingPlayer(this.assignedPlayerData);
		this.assignedPlayer.character.setMovedBySuggestion(false);
		object.setNewLocation(location);
		
	
		NetworkDataWrapper wrapper = new NetworkDataWrapper();
		wrapper.moveData = object;
		// setting appropriate type flag
		wrapper.currentAction = ActionType.USER_ACTION;
		wrapper.currentUserAction = UserActionTypes.PLAYER_MOVE;

		// send data to server
		client.messager.sendData(wrapper);
//		out("Moved: "+wrapper.toString());
	}

	public void stay()
	{
		// creates Player move object with same location, puts into network wrapper 
		ClueCharacter myCharacter = this.assignedPlayerData.character;
		moveToLocation(myCharacter.getLocation());
		myCharacter.setMovedBySuggestion(false);
	}

	public void tryDisproval(Card disprovalCard){
		// creates Disproval object, puts into network wrapper, 
		DisproveData object = new DisproveData();
		object.setDisprovalCard(disprovalCard);
		object.setDisprovingPlayer(this.assignedPlayerData);
		
		NetworkDataWrapper wrapper = new NetworkDataWrapper();
		wrapper.disproval = object;
		// setting appropriate type flag
		wrapper.currentAction = ActionType.USER_ACTION;
		
		wrapper.currentUserAction = UserActionTypes.DISPROVE;
		
		out(wrapper.toString());
		// send data to server
		client.messager.sendData(wrapper);
	}

	public void tryAccusation(Room room, ClueCharacter suspect, Weapon weapon)
	{
		accuseOrSuggestHelper(UserActionTypes.ACCUSE, room, suspect, weapon);
	}

	public void trySuggestion(Room room, ClueCharacter suspect, Weapon weapon){
		accuseOrSuggestHelper(UserActionTypes.SUGGEST, room, suspect, weapon);
	}

	private void accuseOrSuggestHelper(UserActionTypes userActionType, Room room, 
									   ClueCharacter suspect, Weapon weapon) 
	{
		// creates accusation object, puts into NetworkDataWrapper, 
		SuggestOrAccuseData object = new SuggestOrAccuseData();
		object.setSuggestingPlayer(assignedPlayerData);
		
		if ((room == null) && (suspect == null) && (weapon == null))
		{
			object.setPlayerPasses(true);
		}
		else
		{
			object.setPlayerPasses(false);
			object.setRoom(room);
			object.setSuspect(suspect);
			object.setWeapon(weapon);
		}
		object.setAccusation(userActionType.equals(UserActionTypes.ACCUSE));
		NetworkDataWrapper wrapper = new NetworkDataWrapper();
		wrapper.suggestionOrAccusation = object;
		// setting appropriate type flag
		wrapper.currentAction = ActionType.USER_ACTION;
		
		wrapper.currentUserAction = userActionType;
		
		out("USER ACCUSING");
		out(object.getSuggestingPlayer().toString());
		out(wrapper.toString());
		
		// send data to server
		client.messager.sendData(wrapper);
	}
}
